package com.stoney.http;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by Stony on 2015/12/12.
 */
public class BasicNetwork {


    private HttpStack httpStack;
    protected final ByteArrayPool mPool;
    private static int DEFAULT_POOL_SIZE = 4096;
    /**
     *
     * @param httpStack
     */
    public BasicNetwork(HttpStack httpStack) {
        this(httpStack, new ByteArrayPool(DEFAULT_POOL_SIZE));
    }
    public BasicNetwork(HttpStack httpStack, ByteArrayPool pool) {
        this.httpStack = httpStack;
        mPool = pool;
    }

    public NetworkResponse performRequest(Request<?> request) throws Exception {
        while (true) {
            HttpResponse httpResponse = httpStack.performRequest(request,request.getHeaders());
            Map<String, String> responseHeaders = new HashMap<String, String>();
            byte[] responseContents = null;

            StatusLine statusLine = httpResponse.getStatusLine();
            int statusCode = statusLine.getStatusCode();

            responseHeaders = convertHeaders(httpResponse.getAllHeaders());
            /**
             *
             */
            if (statusCode == HttpStatus.SC_NOT_MODIFIED) {
                return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED,
                        null, responseHeaders, true);
            }

            responseContents = entityToBytes(httpResponse.getEntity());

            if (statusCode != HttpStatus.SC_OK && statusCode != HttpStatus.SC_NO_CONTENT) {
                throw new IOException();
            }
            return new NetworkResponse(statusCode, responseContents, responseHeaders, false);
        }
    }

    /** Reads the contents of HttpEntity into a byte[]. */
    private byte[] entityToBytes(HttpEntity entity) throws IOException, RequestFailureError {
        PoolingByteArrayOutputStream bytes =
                new PoolingByteArrayOutputStream(mPool, (int) entity.getContentLength());
        byte[] buffer = null;
        try {
            InputStream in = entity.getContent();
            if (in == null) {
                throw new RequestFailureError();
            }
            buffer = mPool.getBuf(1024);
            int count;
            while ((count = in.read(buffer)) != -1) {
                bytes.write(buffer, 0, count);
            }
            return bytes.toByteArray();
        } finally {
            try {
                // Close the InputStream and release the resources by "consuming the content".
                entity.consumeContent();
            } catch (IOException e) {
                e.printStackTrace();
            }
            mPool.returnBuf(buffer);
            bytes.close();
        }
    }

    /**
     * Converts Headers[] to Map<String, String>.
     */
    private static Map<String, String> convertHeaders(org.apache.http.Header[] headers) {
        Map<String, String> result = new HashMap<String, String>();
        for (int i = 0; i < headers.length; i++) {
            result.put(headers[i].getName(), headers[i].getValue());
        }
        return result;
    }
}
